/* vim: set sw=8 ts=8 sts=8 expandtab: */
#ifndef CMAID_LIST_FUNCDEF_H
#define CMAID_LIST_FUNCDEF_H

/**
 * @def CMAID_LIST_FUNC(c)
 * @ingroup Cmaid_List_Interface
 * Macro to access the list interface.
 */
#define CMAID_LIST_FUNC(c) ((const Cmaid_List_Interface *)(((c)->interface)))

/**
 * @param t the list to append the new data
 * @param data the data to append
 * @return Returns a pointer pointing to the newly appended data
 * @brief Appends a new data node
 *
 * This functions appends a new data node to the list. Depending on the value
 * type the list will allocated space to hold the data and thus may return
 * another pointer then the @p data pointer passed to the functions. The
 * @p data parameter must not be @c NULL.
 */
CMAID_INLINE void *
cmaid_list_append(Cmaid_List *t, const void *data)
{
        CMAID_CHECK_TYPE_RET(t, CMAID_MAGIC_LIST, NULL);
        CMAID_CHECK_POINTER_RET(data, NULL);
        return CMAID_LIST_FUNC(t)->append(t, data);
}

/**
 * @param t the list to prepend the new data
 * @param data the data to prepend
 * @return Returns a pointer pointing to the newly prepended data
 * @brief Prepends a new data node
 *
 * This functions prepends a new data node to the list. Depending on the value
 * type the list will allocated space to hold the data and thus may return
 * another pointer then the @p data pointer passed to the functions. The
 * @p data parameter must not be @c NULL.
 */
CMAID_INLINE void *
cmaid_list_prepend(Cmaid_List *t, const void *data)
{
        CMAID_CHECK_TYPE_RET(t, CMAID_MAGIC_LIST, NULL);
        CMAID_CHECK_POINTER_RET(data, NULL);
        return CMAID_LIST_FUNC(t)->prepend(t, data);
}

/**
 * @param t the list to work with
 * @return Returns no value
 * @brief Remove the first node of the list
 *
 * Remove the first node of the list. If a free function is defined the value
 * will be freed.
 */
CMAID_INLINE void
cmaid_list_first_remove(Cmaid_List *t)
{
        CMAID_CHECK_TYPE(t, CMAID_MAGIC_LIST);
        CMAID_LIST_FUNC(t)->first_remove(t);
}

/**
 * @param t the list to work with
 * @return Returns no value
 * @brief Remove the last node of the list
 *
 * Remove the last node of the list. If a free function is defined the value
 * will be freed.
 */
CMAID_INLINE void
cmaid_list_last_remove(Cmaid_List *t)
{
        CMAID_CHECK_TYPE(t, CMAID_MAGIC_LIST);
        CMAID_LIST_FUNC(t)->last_remove(t);
}

/**
 * @param t the list to work with
 * @return Returns the value of the first node
 * @brief Retrieve the value of the first node
 *
 * Returns the value of the first node. If the list is empty @c NULL will be
 * returned.
 */
CMAID_INLINE void *
cmaid_list_first(Cmaid_List *t)
{
        CMAID_CHECK_TYPE_RET(t, CMAID_MAGIC_LIST, NULL);
        return CMAID_LIST_FUNC(t)->first(t);
}

/**
 * @param t the list to work with
 * @return Returns the value of the last node
 * @brief Retrieve the value of the last node
 *
 * Returns the value of the last node. If the list is empty @c NULL will be
 * returned.
 */
CMAID_INLINE void *
cmaid_list_last(Cmaid_List *t)
{
        CMAID_CHECK_TYPE_RET(t, CMAID_MAGIC_LIST, NULL);
        return CMAID_LIST_FUNC(t)->last(t);
}

/**
 * @param t the list to insert the new data
 * @param data the data to insert
 * @param iter the iterator which defines the position
 * @return Returns a pointer pointing to the new data
 * @brief Insert a new data node
 *
 * This functions inserts a new data node to the list. Depending on the value
 * type the list will allocated space to hold the data and thus may return
 * another pointer then the @p data pointer passed to the functions. The
 * @p data parameter must not be @c NULL.
 */
CMAID_INLINE void *
cmaid_list_insert_before(Cmaid_List *t, Cmaid_Iter *iter, const void *data)
{
        CMAID_CHECK_TYPE_RET(t, CMAID_MAGIC_LIST, NULL);
        CMAID_CHECK_POINTER_RET(data, NULL);
        return CMAID_LIST_FUNC(t)->insert_before(t, iter, data);
}

/**
 * @param t the list to insert the new data
 * @param data the data to insert
 * @param iter the iterator which defines the position
 * @return Returns a pointer pointing to the new data
 * @brief Insert a new data node
 *
 * This functions inserts a new data node to the list. Depending on the value
 * type the list will allocated space to hold the data and thus may return
 * another pointer then the @p data pointer passed to the functions. The
 * @p data parameter must not be @c NULL.
 */
CMAID_INLINE void *
cmaid_list_insert_after(Cmaid_List *t, Cmaid_Iter *iter, const void *data)
{
        CMAID_CHECK_TYPE_RET(t, CMAID_MAGIC_LIST, NULL);
        CMAID_CHECK_POINTER_RET(data, NULL);
        return CMAID_LIST_FUNC(t)->insert_after(t, iter, data);
}

/**
 * @param t the list to sort
 * @return Returns no value
 * @brief Sorts the list
 *
 * This function sorts the list using the natrual compare function of the data
 * type, typically the compare function defined by the Cmaid_Value passed
 * on the creation of the list.
 */
CMAID_INLINE void
cmaid_list_sort(Cmaid_List *t)
{
        CMAID_CHECK_TYPE(t, CMAID_MAGIC_LIST);
        CMAID_LIST_FUNC(t)->sort_with(t, NULL);
}

/**
 * @param t the list to sort
 * @param cmp the compare function
 * @return Returns no value
 * @brief Sorts the list with a given compare function
 *
 * This function will sort the list with the given compare function @p cmp. If
 * @p cmp is equal @c NULL the result will be the same like calling
 * cmaid_list_sort().
 */
CMAID_INLINE void
cmaid_list_sort_with(Cmaid_List *t, Cmaid_Value_Compare_Cb cmp)
{
        CMAID_CHECK_TYPE(t, CMAID_MAGIC_LIST);
        CMAID_LIST_FUNC(t)->sort_with(t, cmp);
}

/**
 * @param t the list to reverse
 * @return Returns no value
 * @brief Reverse the list
 */
CMAID_INLINE void
cmaid_list_reverse(Cmaid_List *t)
{
        CMAID_CHECK_TYPE(t, CMAID_MAGIC_LIST);
        CMAID_LIST_FUNC(t)->reverse(t);
}

#endif
